﻿/**
 * \file Unite.cs
 * \brief Classe Unite
 * \author ARTUR Vincent
 * \author LAPERDRIX Pierre
 * \version 1.0
 */
namespace Implem
{
    using Interfaces;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;

    /**
     * \class Unite
     * \brief Objet representant une unite
     */
    public abstract class Unite : IUnite
    {

        /*!< Joueur proprietaire de cette unite */
        protected Joueur _joueurProprietaire;

        /*!< Propriete accedant a l'attribut _coutMinerai */
        public virtual Joueur JoueurProprietaire
        {
            get { return _joueurProprietaire; }
            set { _joueurProprietaire = value; }
        }

        /*!< Cout en minerai de l'unite */
        protected int _coutMinerai;

        /*!< Propriete accedant a l'attribut _coutMinerai */
        public virtual int CoutMinerai
        {
            get { return _coutMinerai; }
            set { _coutMinerai = value; }
        }

        /*!< Points d'attaque de l'unite */
        protected int _attaque;

        /*!< Propriete accedant a l'attribut _attaque */
        public virtual int Attaque
        {
            get { return _attaque; }
            set { _attaque = value; }
        }

        /*!< Points de defense de l'unite */
        protected int _defense;

        /*!< Propriete accedant a l'attribut _defense */
        public virtual int Defense
        {
            get { return _defense; }
            set { _defense = value; }
        }

        /*!< Mouvements restants de l'unite pour le tour courant */
        protected int _movRest;

        /*!< Propriete accedant a l'attribut _movRest */
        public virtual int MovRest
        {
            get { return _movRest; }
            set { _movRest = value; }
        }

        /*!< Nombre de mouvements par tour de l'unite */
        protected int _mouvement;

        /*!< Propriete accedant a l'attribut _mouvement */
        public virtual int Mouvement
        {
            get { return _mouvement; }
            set { _mouvement = value; }
        }

        /*!< Points de vie de l'unite */
        protected int _vie;

        /*!< Propriete accedant a l'attribut _vie */
        public virtual int Vie
        {
            get { return _vie; }
            set { _vie = value; }
        }

        /*!< Position courante de l'unite */
        protected Position _posit;

        /*!< Propriete accedant a l'attribut _posit */
        public virtual Position Posit
        {
            get { return _posit; }
            set { _posit = value; }
        }

        /*!< Points de vie de l'unite a sa creation */
        protected int _vieC;

        /*!< Propriete accedant a l'attribut _vieC */
        public virtual int VieC
        {
            get { return this._vieC; }
            set { _vieC = value; }
        }

        /*< Booleen indiquant si l'unite a ete utilisee durant le tour */
        protected bool _used;

        /*!< Propriete accedant a l'attribut _used */
        public virtual bool Used
        {
            get { return _used; }
            set { _used = value; }
        }

        /*!< Events permettant d'informer l'observateur de la suppression de l'unite */
        public event EventHandler<SuppressionEventArgs> SuppressionEvent;

        /*!< Classe permettant d'envoyer la commande de suppression de l'unite*/
        public class SuppressionEventArgs : EventArgs
        {
            public Unite unite { get; set; }
        }

        /**
         * \fn public Unite(Joueur j, Position p)
         * \brief Constructeur d'Unite
         * \param j le joueur proprietaire de l'unite
         * \param p la position de l'unite
         */
        public Unite(Joueur j, Position p)
        {
            JoueurProprietaire = j;
            Posit = p;
            Used = false;
        }

       

        /**
         * \fn public virtual void priseVille()
         * \brief Prend une ville a un adversaire
         */
        public virtual void priseVille()
        {
            //Recuperation de la ville
            Ville v = (Ville)Carte.Villes[this.Posit];
            
            //Changement de joueur
            Joueur tmp = v.JoueurProprietaire;
            v.JoueurProprietaire = Partie.joueurCourant;
            Partie.joueurCourant.Villes.Add(v);

            //Mise a jour de la vue
            v.priseVille(tmp,Partie.joueurCourant);
        }

        /**
         * \fn public virtual vois pertePV(int pvRestants)
         * \brief Enleve a l'unite les PV perdus au cours d'un combatt
         * \param pvRestants le nombre de PV restants apres le combat
         */
        public virtual void pertePV(int pvRestants)
        {
            if (pvRestants <= 0) deceder();
            else this.Vie = pvRestants;

        }

        /**
         * \fn public virtual void gainPV()
         * \brief Fait regagner un PV a l'unite si celle-ci n'a pas ete utilisee durant le tour
         */
        public virtual void gainPV()
        {
            if (!_used && _vie<_vieC)
            {
                _vie++;
            }
            else
            {
                Used = false;
            }

        }

        /**
         * \fn public virtual void refreshMouvement()
         * \brief Remet le nombre de mouvements possibles de l'unite a sa valeur initiale
         */
        public virtual void refreshMouvement()
        {
            MovRest = Mouvement;
        }


        /**
         * \fn public virtual void deceder()
         * \brief Fait mourrir l'unite en jouant une musique dramatique
         */
        public virtual void deceder()
        {
            Console.WriteLine("Je meurs ! ... *musique dramatique*");

            //Suppression de l'unite sur la carte
            Carte.suppressionUnite(this);

            //Suprression de l'unite de la liste du joueur
            if (this is IEnseignant)
            {
                this.JoueurProprietaire.Enseignants.Remove((IEnseignant)this);
            }
            else if(this is IEtudiant)
            {
                this.JoueurProprietaire.Etudiants.Remove((IEtudiant)this);
            } else 
            {
                this.JoueurProprietaire.Directeur = null;
            }

            //Envoi a l'observateur de la commande de suppression
            EventHandler<SuppressionEventArgs> handler = SuppressionEvent;
            //Creation d'un SuppressionEventArgs
            SuppressionEventArgs args = new SuppressionEventArgs();
            args.unite = this;

            if (handler != null)
            {
                handler(this, args);
            }
        }

        /**
         * \fn public abstract void seDeplacer(Position p)
         * \brief Deplace l'unite a la position p
         * \param p la position
         */
        public abstract void seDeplacer(Position p);

        /**
         * \fn public virtual void save(StreamWriter sw)
         * \brief Sauvegarde de l'unite
         * \param sw le flux dans lequel ecrire
         */
        public virtual void save(StreamWriter sw)
        {
            sw.WriteLine(Attaque);
            sw.WriteLine(Defense);
            sw.WriteLine(Mouvement);
            sw.WriteLine(Vie);
            sw.WriteLine(VieC);
            sw.WriteLine(MovRest);
            sw.WriteLine(CoutMinerai);
            if (Used) sw.WriteLine('1');
            else sw.WriteLine('0');
            sw.WriteLine(Posit.X);
            sw.WriteLine(Posit.Y);
        }

        /**
         * \fn public virtual void load(StreamReader sr,Joueur j)
         * \brief Chargement de l'unite
         * \param sr le flux dans lequel lire
         * \param j le proprietaire de l'unite
         */
        public virtual void load(StreamReader sr, Joueur j)
        {
            Attaque = Convert.ToInt32(sr.ReadLine());
            Defense = Convert.ToInt32(sr.ReadLine());
            Mouvement = Convert.ToInt32(sr.ReadLine());
            Vie = Convert.ToInt32(sr.ReadLine());
            VieC = Convert.ToInt32(sr.ReadLine());
            MovRest = Convert.ToInt32(sr.ReadLine());
            CoutMinerai = Convert.ToInt32(sr.ReadLine());
            char c = (char)sr.Read();
            Used = ((c == '1') ? true : false);
            sr.ReadLine();
            int x = Convert.ToInt32(sr.ReadLine());
            int y = Convert.ToInt32(sr.ReadLine());
            Posit = new Position(x, y);
            if (Carte.Unites.ContainsKey(Posit))
            {
                List<Unite> lu = Carte.Unites[Posit];
                lu.Add(this);
                Carte.Unites[Posit] = lu;
            }
            else
            {
                List<Unite> lu = new List<Unite>();
                lu.Add(this);
                Carte.Unites[Posit] = lu;
            }
        }

        public override string ToString()
        {
            if (this is EtudiantEII) return "Etudiant EII";
            if (this is EtudiantINFO) return "Etudiant INFO";
            if (this is EnseignantEII) return "Enseignant EII";
            if (this is EnseignantINFO) return "Enseignant INFO";
            if (this is DirecteurEII) return "Directeur EII";
            if (this is DirecteurINFO) return "Directeur INFO";
            else return "404 not found";

        }



    }
}

